﻿<html>
  <head>
    <title>CSSS!(CSS脚本)语言</title> 
    <meta name="generator" content="h-smile:richtext"/>
  </head>
<body>
  <h1>CSSS!(CSS脚本)语言</h1>
  <h2>简介</h2>
  <p>CSSS!是对传统的CSS(层叠样式表)的脚本化扩展，它使CSS有了可以给某些元素定义一些基本行为样式。</p>
  <div>CSSS!可以出现在:
    <ul>
    <li>a) 属性名以'!'结尾的标记;</li> 
    <li>b) 在<a href="csss!-calc-function.htm"><code>calc()</code></a>函数内部。</li> 
    </ul>
  </div>
  <p>这里是h-smile引擎支持的<a href="csss!-events.htm">CSS属性的有效规则列表</a>。</p>
  <p>示例, 下面这个是<code>&lt;label for=&quot;id&quot;&gt;</code>的一个功能实现，这个功能也可以适用定义了<code>for=&quot;id&quot;</code>属性的元素:</p>
  <pre>   [for]
   {
     hover-on!  : $1(#&lt; self.for &gt;):hover = true;
     hover-off! : $1(#&lt; self.for &gt;):hover = false;
     active-on! : $1(#&lt; self.for &gt;):focus = true;
     cursor:pointer;
   }
   input:hover
   {
     outline: 4px glow blue 1px;
   }
</pre>
  <p><code>hover-on</code>和<code>hover-off</code>规则使label的绑定元素获取<em>:hover</em>状态。所以当鼠标悬停在label上时等同于停留在绑定元素上。<code>active-on!:</code>规则使绑定元素获取焦点。</p>
  <p><code>$1(...)</code>的含义参见下面的<em>Selector pseudo-functions</em>章节。</p>
  <h2>CSSS!语法</h2>
  <p>CSSS!嵌入到宿主CSS语法中。CSSS!中使用标识符/构造器有些限制，CSSS!语句中不能使用<code>';'</code>、<code>'{'</code>和<code>'}'</code>标识符。';'标识符作为CSSS!脚本的结束标志。</p>
  <h3>标识符</h3>
  <p>标识符(nmtokens)以<em>字母</em>、'-'、'_'或'$'字符开头，后面跟着一些<em>字母</em>、'-'、'_'、'$'或数字([0-9])。注意'-'标识符, 因为是CSS语法，所以这个字符也可以作为名称的一部分。为了解决与减号'-'的冲突，减号两边必须有空格符。</p>
  <pre class="code">nmtoken -&gt; [a-zA-Z_\-$]+[a-zA-Z_\-$0-9]*
</pre>
  <h3>关键字</h3>
  <p>CSSS!可以有以下关键字:</p>
  <pre>true   false   null   self
</pre>
  <h3><a name="operators" id="operators">操作符</a></h3>
  <pre class="code">&lt;     &gt;     &lt;=    ==    !=    &gt;=    &amp;&amp;    ||
+     -     *     /     %     ^     |     &amp;
</pre>
  <p>[tbd]</p>
  <p>下个版本要支持的操作符:</p>
  <pre>~=    ~/    ~%    %~    /~
</pre>
  <p>三元操作符: &nbsp;</p>
  <pre>&lt;条件&gt; <strong>?</strong> &lt;true-部分&gt; [ <strong>#</strong> &lt;false-部分&gt; ]
</pre>
  <p>注意，三元操作符可以作为条件语句(if ... then ... else ...):</p>
  <code>self:value &gt; 12 ?( self:current = true, self.scroll-to-view())</code>; - 如果<em>self</em>元素的value值大于12，则设置self为当前元素，并将该元素滚动到视图。
  <h3>数据类型</h3>
  <p>CSSS!是一种无类型语言。所有变量可以设置下面的这些类型的值:</p>
  <ul>
    <li>null - 无值;</li>
    <li><em>boolean</em> 有两个值: <em>true</em>和<em>false</em>;</li>
    <li><em>integer</em> - 32位有符号整数;</li>
    <li><em>float</em> - 64位浮点数;</li>
    <li><em>string</em> - UNICODE字符串;</li>
    <li><em>object</em> - DOM元素的引用;</li>
    <li><em>object-set</em> - 特别的对象，它表示一个DOM元素集合。$()函数返回这样的值。</li>
    <li><em>function-reference</em> - CSSS!中声明的函数引用。</li></ul>
  <p>不支持聚合类型(如数组)。</p>
  <h3>字面值</h3>
  <p>接受整数、浮点数、字符串、<strong>长度单位</strong>和正则表达式:</p>
  <pre class="code">整数描述 -&gt; [0-9]+ | '0x' [0-9A-Fa-f]+ | ''' 字符 ''' | key-code-literal
  浮点数描述 -&gt; [0-9]+ '.' [0-9]+
  浮点数描述 -&gt; [0-9]+ '.' 'e'|'E' '+'|'-' [0-9]+
  字符串描述 -&gt; '&quot;' [.]* '&quot;'
  正则表达式描述 -&gt; '/' &lt;单行正则表达式&gt; ['/ig'] ';'
  长度单位描述 -&gt; &lt;整数描述&gt; | &lt;浮点数描述&gt; 后面立即跟着:
                   'pt' | 'px' | 'pc' | '%' | 'em' | 'ex' | 'in' | 'cm' | 'mm'
</pre>
  <p><em>Key-code-literal</em>是以单引号括住的字符串，可以为以下值:</p>
  <code>'RETURN' | 'LEFT' | 'RIGHT' | 'UP' | 'DOWN' | 'PRIOR' | 'NEXT' | 'TAB' | 'HOME' | 'END' | 'DELETE' | 'INSERT' | 'BACK'</code>
  <p>要定义类似Ctrl+X的组合键，请在按键的预定义名称前以<code>'^'</code>字符开头。</p>
  <p> 示例:</p>
  <pre class="code">            34 - 整数
    0xAFED1234 - 整数
          1.52 - 浮点数
          1.e2 - 浮点数
         1.e-2 - 浮点数
&quot;Hello world!&quot; - 字符串
          12pt - 长度值，这是表示12像素。
           'A' - 字符'A'的代码, 整数
</pre><em>key-code-literal</em>的数量s:
  <pre>key-on!:
  key-code() == '^A'? ... # // 按下Ctrl+A
  key-code() == '^NEXT'? ... ; // 按下Ctrl+PgDown
</pre>
  <h3><a name="comments" id="comments">注释</a></h3>
  <p> 注释是一个被编译器忽略的字符序列。有两种类型的注释:</p>
  <ul>单行注释:</ul>
  <pre class="code">'//' &lt;text-no-crlf&gt; end-of-line
</pre>
  <ul>多行注释:</ul>
  <pre class="code">'/*' &lt;text&gt; '*/'
</pre>
  <h2><a name="statements" id="statements">语句</a></h2>
  <p>CSSS!程序是一个由逗号(<code>','</code>)分隔的语句序列，并且脚本结尾以<code>';'</code>结束。CSSS!脚本支持以下语句:</p>
  <h4>赋值:</h4>
  <pre>&lt;左表达式&gt; '=' &lt;表达式&gt;.
</pre>
  <h4>声明变量:</h4>
  <pre>&lt;变量名&gt; <strong>'='</strong> &lt;表达式&gt;
</pre>
  <h4>语句块</h4>
  <p>语句块是一个以逗号分隔的表达式列表:</p>
  <pre><strong>'('</strong> &lt;表达式&gt; [, &lt;表达式&gt;]* <strong>')'</strong>
</pre>
  <p>语句块的值等于列表中最后一个表达式的值。</p>
  <h4>条件语句</h4>
  <pre>&lt;逻辑表达式&gt; <strong>'?'</strong> &lt;当true时的表达式&gt; [ <strong>'#'</strong> &lt;当false时的表达式&gt; ]
</pre>
  <p>逻辑表达式用于求值，求值为<code>true</code>时，则对'?'右边的表达式进行求值，否则对'#'右边的表达式进行求值。'#'右边的部分可以省略。</p>
  <h4>循环</h4>
  <p>CSSS!不支持循环(不过提供了一种函数中的尾递归功能可以实现类似的功能)。</p>
  <h4>返回语句</h4>
  <p><code>return</code>语句用于函数中返回值:</p>
  <pre>return &lt;返回的值或表达式&gt;
</pre>
  <h4>For each枚举</h4>
  <pre>&lt;object-set&gt; <strong>'-&gt;'</strong> &lt;有一个参数的函数引用&gt;
</pre>
  <p>枚举用于为左边object-set中的每个元素调用一个函数。object-set由伪函数<code>$()</code>、<code>$p()</code>和<code>$c()</code>产生——满足括号中选择器的DOM元素集合。</p>
  <p>示例:</p>
  <pre>     input.number
     {
       value-changed! :
         total = 0,
         $(input.number) -&gt; @(el) total = total + el:value,
         $1(td#total):value = total;
     }
</pre>
  <p>上面的代码的含义:</p>
  <p>当一些<code>&lt;input class=&quot;number&quot;&gt;</code>元素的值修改时，做以下部分:</p>
  <ul>
    <li>初始化<em>total</em>变量为0。</li>
    <li>声明函数<code>@(el) total = total + el:value</code>。</li>
    <li>为所有满足<code>input.number</code>选择器的DOM元素调用这个函数。</li>
    <li>将total赋值给第一个满足<code>td#total</code>选择器的元素。</li></ul>
  <h4>DOM属性和状态访问</h4>
  <p>DOM元素的属性可以使用'.'语句来访问:</p>
  <pre>&lt;object-or-object-set&gt; '.' &lt;attribute-name&gt;
</pre>
  <p>示例, 对于<code>&lt;input type=&quot;text&quot;&gt;</code>元素，下面的代码:</p>
  <pre>t = self.type
</pre>
  <p>将会返回DOM元素名为&quot;type&quot;的属性的值(这里值是文本)，并且将它赋值给变量<code>t</code>。</p>
  <p>DOM元素的State字段(运行期值)可以通过下面的语句访问:</p>
  <pre>&lt;object-or-object-set&gt; ':' &lt;state-name&gt;
</pre>
  <p>其中，<em>state-name</em>是CSS可识别的一个状态标识的名称: &nbsp;<code>:hover</code>, <code>:active</code>, <code>:link</code>, &nbsp;<code>:checked</code>, <code>:current</code>等。</p>
  <h4>CSS属性访问</h4>
  <p>DOM元素的CSS属性可以通过'::'语句来访问:</p>
  <pre>&lt;object&gt; '::' &lt;css-attribute-name&gt;
</pre>
  <p>示例, 下面的计时器事件处理函数中将会逐渐时元素变得透明:</p>
  <pre>     timer!: self::opacity &lt; 1.0?
               self::opacity = self::opacity + 0.1 #
               return cancel;
</pre>
  <h2>Self</h2>
  <p><code>self</code>关键字指代规则应用的<a href="csss!-dom-object.htm">对象(DOM元素)</a>。</p>
  <h2>Cancel</h2>
  <p><code>cancel</code>关键字一个特殊值，用于<code>return</code>语句，用于运行期停止事件继续传播。</p>
  <h2>函数</h2>
  <p>CSSS!只支持(故意的)匿名自定义函数。</p>
  <h4>函数声明</h4>
  <p>函数使用以下语句声明:</p>
  <pre>'@(' &lt;参数列表&gt; ')' &lt;语句&gt; | &lt;语句块&gt;
</pre>
  <p>其中，<code>&lt;参数列表&gt;</code>是一个以逗号分隔的名称列表。</p>
  <p>函数可以赋值给变量:</p>
  <pre>foo = @(p1, p2) p1 + p2, ...</pre>
  <pre>foo = @(p1, p2) (p1 + p2, ...), ...</pre>
  <p>声明的函数有<code>p1</code>和<code>p2</code>两个参数，和<code>p1 + p2</code>或(p1 + p2, ...)函数体，并且将函数引用赋值给<code>foo</code>变量。</p>
  <h4>函数调用</h4>
  <p>调用函数的语句为:</p>
  <pre>&lt;variable&gt; <strong>'('</strong> &lt;expression-1&gt; , ... &lt;expression-n&gt; <strong>')'</strong>
</pre>
  <p>示例, 下面的代码将会调用上面的<em>foo</em>函数，并且将函数的返回值设置到<em>bar</em>变量:</p>
  <pre>bar = foo(1,2)
</pre>
  <h2>全局函数</h2>
  <h3>选择器函数</h3>
  <p>有两个全局函数:</p>
  <ol>
    <li><code><strong>$</strong>(selector)</code><strong> - </strong>全局选择元素，<code>:root</code>为文档的根元素。</li>
    <li><code><strong>$1</strong>(selector)</code> - returns <a href="csss!-dom-object.htm">object</a> - 匹配选择器的第一个元素。<code>:root</code>为文档的根元素。</li></ol>
  <p>$()函数返回一个选择的DOM元素的集合(可能为空)。$1()函数返回一个DOM元素——匹配选择器的第一个元素。</p>
  <p>选择器函数支持拼接值，格式为:<code>$( ... &lt;value&gt; ... )</code>, 其中，值包含'&lt;'和'&gt;'括号。 <br/>
  示例, 下面的语句:</p>
  <pre>ncol = 2, $( table td:nth-child(&lt; ncol &gt;)).some-attr = &quot;hi!&quot;;
</pre>
  <p>将会为所有满足<code>table td:nth-child(2)</code>选择器的元素的<em>some-attr</em>属性设置值为&quot;hi!&quot;。</p>
  <h3>其他函数</h3>
  <ul>
    <li><code><strong>int</strong>(val)</code>- 转换val的值为整数;</li>
    <li><code><strong>float</strong>(val)</code>- 转换val的值为浮点数;</li>
    <li><code><strong>length</strong>(val)</code> - 转换val的值为length单位值;</li>
    <li><code><strong>min</strong>(val1, val2 ... valN)</code>- 返回参数中的最小值;</li>
    <li><code><strong>max</strong>(val1, val2 ... valN)</code>- 返回参数中的最大值;</li>
    <li><code><strong>limit</strong>(val, minval, maxval)</code> - 如果var在[minval...maxval]范围内则返回val，如果var小于minval则返回minval，否则返回maxval。</li></ul>
  <h3>String对象的属性和方法</h3>
  <ul>
    <li><code><em>string</em><strong>.length</strong></code> - 属性, <em>string</em>对象的长度;</li>
    <li><code><em>string</em><strong>.toUpper()</strong></code> - 方法, 字符串的大写形式版本;</li>
    <li><code><em>string</em><strong>.toLower()</strong></code> - 方法, 字符串的小写形式版本;</li>
    <li><code><em>string</em><strong>.substr(</strong>start[, length = -1]<strong>)</strong></code> - 方法, 返回一个子字符串，如果length小于0，则返回字符串的其余部分。</li></ul>
</body>
</html>
